<?php
/**
 * SDTC 操作类，内部操作暂用TTC
 * 封装所有相关的SDTC操作
 */
define( "TPHP_TTC_OP_GET",      4 );
define( "TPHP_TTC_OP_PURGE",    5 );
define( "TPHP_TTC_OP_INSERT",   6 );
define( "TPHP_TTC_OP_UPDATE",   7 );
define( "TPHP_TTC_OP_DELETE",   8 );
define( "TPHP_TTC_OP_FLUSH",    13 );

define( "TPHP_TTC_KEYTYPE_NONE", 0 );
define( "TPHP_TTC_KEYTYPE_INT", 1 );
define( "TPHP_TTC_KEYTYPE_STRING", 4 );
/*
if ( !extension_loaded('tphp_ttc') )
{
    if ( !ini_get("safe_mode") && ini_get("enable_dl") )
    {
        if ( !@dl("tphp_ttc.so") )
        {
            $suffix  = ".".TPHP_LIB_VERSTR;
            $suffix .= ".libc-".tphp_get_libcver();
            if ( !dl("tphp_ttc.so".$suffix) )
            	trigger_error('无法加载sdtc', E_USER_ERROR);
        }
    }
    else
        trigger_error('无法加载sdtc', E_USER_ERROR);
}
*/
class SdtcOp
{
	private $ttc_srv;
//	private $ttc_req;
//	private $ttc_res;
	private $table_cfg;
	private $key_field_count;

	public function __construct()
	{
		$this->ttc_srv = NULL;
//		$this->ttc_req = NULL;
//		$this->ttc_res = NULL;
		$this->table_cfg = array();
		$this->key_field_count = 0;
	}

    public function __destruct()
    {
    }

    /**
     *  通过表别名取得对应的 sdtc操作实例
     * @param string $table_alias: 实例的配置项表别名
     * @return obj: sdtc操作实例
     */
    public static function getInstance($table_alias)
    {
        $sdtc = get_instance_of(__CLASS__, 'init', (array)$table_alias);
        return $sdtc;
    }

    /**
     * 通过表别名初始化sdtc实例
     *
     */
    public function init($table_alias)
    {
		//获取配置
		$sdtc_cfg = C("__SDTC_CONFIG");
		$this->table_cfg = $sdtc_cfg[$table_alias];
    	if (!isset($this->table_cfg))
			trigger_error(__FUNCTION__.':sdtc配置里没有定义表['.$table_alias.']的sdtc配置信息', E_USER_ERROR);

		if (empty($this->table_cfg["HOST"]) || empty($this->table_cfg["PORT"]) || empty($this->table_cfg["TABLE_NAME"])
			|| empty($this->table_cfg["FIELD_DEFINE"]) || !is_array($this->table_cfg["FIELD_DEFINE"]))
		{
			trigger_error(__FUNCTION__.':表['.$table_alias.']的sdtc配置信息有误，请检查配置 ', E_USER_ERROR);
		}
		if (empty($this->table_cfg["TIMEOUT"]))
			$this->table_cfg["TIMEOUT"] = 60;
		if ( empty($this->table_cfg["PRIMARY_KEY"]))
			$this->table_cfg["PRIMARY_KEY"] = key($this->table_cfg["FIELD_DEFINE"]);
		if ( !is_array($this->table_cfg["PRIMARY_KEY"]) )
			$this->table_cfg["PRIMARY_KEY"] = (array)$this->table_cfg["PRIMARY_KEY"];
		$this->key_field_count = count($this->table_cfg["PRIMARY_KEY"]);

		//建立server对象，连接sdtc
		$this->ttc_srv = new tphp_ttc_server();
		$this->ttc_srv->set_address(gethostbyname($this->table_cfg["HOST"]), $this->table_cfg["PORT"]);
		$this->ttc_srv->set_tablename($this->table_cfg["TABLE_NAME"]);
		$this->ttc_srv->set_timeout($this->table_cfg["TIMEOUT"]);
		foreach ($this->table_cfg["PRIMARY_KEY"] as $key_name)
		{
			$key_type = $this->table_cfg["FIELD_DEFINE"][$key_name];
			switch ($key_type)
			{
				case "int":
					$this->ttc_srv->add_key($key_name, TPHP_TTC_KEYTYPE_INT);
					break;
				case "string":
					$this->ttc_srv->add_key($key_name, TPHP_TTC_KEYTYPE_STRING);
					break;
				default:
					trigger_error(__FUNCTION__.':表['.$table_alias.']的sdtc配置信息有误，请检查key的配置 ', E_USER_ERROR);
					break;
			}
		}

		// 是否开启调试
		if (C('APP_DEBUG')) $this->debug = true;
    }

    /**
     * 取指定key的数据，支持批量
     * @param $key: key字段的值, 单key可以直接传key的值，多key（key字段有多个）或 array('key_field1'=>key_value1,....), 批量查询传由以上数据类型组成的二维数组
     * @return : 根据传入的key，返回单行数据（一维数组）或多行数据（二维数组）,查询不到返回false
     */
	public function get($key)
	{
		//多key时，传入的参数必须是数组
		if ( $this->key_field_count<0 || empty($key) || ( $this->key_field_count>1 && !is_array($key) ) )
			return false;
		//判断是否传入了多个key
		$bMutilKey = false;
		if ( is_array($key) && is_numeric(key($key)) )
		{
			$bMutilKey = true;
		}

		//构建查询语句
		$ttc_req = new tphp_ttc_request($this->ttc_srv, TPHP_TTC_OP_GET);
		//非批量查询，统一转化为批量查询
		if (!$bMutilKey)
			$keys = array($key);
		else $keys = $key;
		foreach ($keys as $item)
		{
			$item = (array)$item;
			foreach ($item as $k=>$v)
			{
				//单key，允许忽略字段名，直接传value
				if (is_numeric($k))
					$k = $this->table_cfg["PRIMARY_KEY"][$k];

				$key_type = $this->table_cfg["FIELD_DEFINE"][$k];
				switch ($key_type)
				{
					case "int":
						$ttc_req->addkey_value($k, $v);
						break;
					case "string":
						$ttc_req->addkey_value_str($k, $v);
						break;
					default:
						trigger_error(__FUNCTION__.':表['.$table_alias.']的sdtc配置信息有误，请检查key的配置 ', E_USER_ERROR);
						break;
				}
				/*
				if ( in_array($k, $this->table_cfg["PRIMARY_KEY"], true) )
					$ttc_req->addkey_value($k, $v);
				//单key，允许忽略字段名，直接传value
				else if (is_numeric($k)&& $k==0)
					$ttc_req->addkey_value($this->table_cfg["PRIMARY_KEY"][$k], $v);*/
			}
		}

		//指定需要返回的字段
		foreach( $this->table_cfg["FIELD_DEFINE"] as $field=>$type)
			$ttc_req->need($field);

	    //执行，得到结果
        $ttc_res = new tphp_ttc_result();
        $ttc_req->execute($ttc_res);

		//导出结果
		$ret = array();
		$res_code = $ttc_res->result_code();
		if ($res_code==0)
		{
			$numrows= $ttc_res->num_rows();
			for ($i=0; $i<$numrows; $i++)
			{
				$ttc_res->fetch_row();
				$temp = array();
				foreach ($this->table_cfg["FIELD_DEFINE"] as $field=>$type)
				{
					$method = $type."_value";
					$temp[$field] = $ttc_res->$method($field);
					/*if (!isset($temp[$field]))
					{
						switch ($type)
						{
							case "int":
							case "float":
								$temp[$field] = 0;
								break;
							case "string":
							case "binary":
								$temp[$field] = "";
								break;
						}
					}*/
				}
				array_push($ret, $temp);
			}
		}

		//根据输入调整结果
		if ( !$bMutilKey )
			$ret = array_shift($ret);
		if (empty($ret))
			return false;
		return $ret;
	}

	/**
	 * 设置key对应的记录
	 * @param $key：要设置的key，单key下可以直接传value，多key必须传数组  array('key_field1'=>key_value1,....)
	 * @param array sets: 需要设置的字段集合，格式：array("filed1"=>value1,"filed2"=>array("op"=>["add"|"sub"],"value"=1),...)
	 * @return: true or false
	 */
	public function set($key, $sets)
	{
		$keys = (array)$key;
		//先嘗試更新，失敗再插入
		$op_types = array(TPHP_TTC_OP_UPDATE, TPHP_TTC_OP_INSERT);
		foreach ($op_types as $op_type)
		{
			//構造查詢語句
			$ttc_req = new tphp_ttc_request($this->ttc_srv, $op_type);
			foreach ($keys as $k=>$v)
			{
				//单key，允许忽略字段名，直接传value
				if (is_numeric($k))
					$k = $this->table_cfg["PRIMARY_KEY"][$k];

				$key_type = $this->table_cfg["FIELD_DEFINE"][$k];
				switch ($key_type)
				{
					case "int":
						$ttc_req->addkey_value($k, $v);
						break;
					case "string":
						$ttc_req->addkey_value_str($k, $v);
						break;
					default:
						trigger_error(__FUNCTION__.':表['.$table_alias.']的sdtc配置信息有误，请检查key的配置 ', E_USER_ERROR);
						break;
				}
			}

			$op_allows = array("add", "sub");
			foreach ($this->table_cfg["FIELD_DEFINE"] as $field=>$type)
			{
				if (in_array($field, $this->table_cfg["PRIMARY_KEY"], true))
					continue;
				switch ($type)
				{
					case "int" :
						//对整形或浮点的字段，可以用set/sub/add方法
						if ( isset($sets[$field]) )
						{
							if (!is_array($sets[$field]))
								$ttc_req->set($field, $sets[$field]);
							else
							{
								if ($op_type==TPHP_TTC_OP_UPDATE)
								{
									$op = $sets[$field]["op"];
									if ( in_array($op, $op_allows, true) )
										$ttc_req->$op($field, $sets[$field]["value"]);
								}
								else
									$ttc_req->set($field, $sets[$field]["value"]);
							}
						}
						break;
					case "float" :
						if ( isset($sets[$field]) )
						{
							if (!is_array($sets[$field]))
								$ttc_req->set_flo($field, $sets[$field]);
							else
							{
								if ($op_type==TPHP_TTC_OP_UPDATE)
								{
									$op = $sets[$field]["op"];
									if ( in_array($op, $op_allows, true) )
									{
										$op = $op."_flo";
										$ttc_req->$op($field, $sets[$field]["value"]);
									}
								}
								else
									$ttc_req->set($field, $sets[$field]["value"]);
							}
						}
						break;
					case "string":
						if ( isset($sets[$field]) )
							$ttc_req->set_str($field, $sets[$field]);
						break;
					case "binary":
						if ( isset($sets[$field]) )
							$ttc_req->set_bin($field, $sets[$field]);
						break;
					default :
						break;
				}
			}

			//执行，得到结果
			$ttc_res = new tphp_ttc_result();
			$ttc_req->execute($ttc_res);

			//导出结果
			$res_code = $ttc_res->result_code ();
			if ($res_code==0 && $ttc_res->affected_rows()>0)
				 return true;
		}
		return false;
	}
}